package com.fastwire.carriere.controller.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import com.fastwire.carriere.common.constant.AppConstants;
import com.fastwire.carriere.common.mapper.TPNameMapper;
import com.fastwire.carriere.common.util.CommonLogger;
import com.fastwire.carriere.common.util.StringUtil;
import com.fastwire.carriere.controller.TerminationPointController;
import com.fastwire.carriere.dao.CrossConnectBandwidthDao;
import com.fastwire.carriere.dao.DAOException;
import com.fastwire.carriere.dao.DAOFactory;
import com.fastwire.carriere.inventory.entity.CrossConnect;
import com.fastwire.carriere.inventory.entity.CrossConnectBandwidth;
import com.fastwire.carriere.inventory.entity.TerminationPoint;
import com.fastwire.carriere.inventory.vo.CrossConnectVo;
import com.fastwire.carriere.inventory.vo.EquipmentVo;
import com.fastwire.carriere.inventory.vo.FDFrVo;
import com.fastwire.carriere.inventory.vo.TerminationPointVo;
import com.fastwire.carriere.inventory.vo.TopologicalLinkVo;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;

public class TerminationPointControllerImpl implements
		TerminationPointController {

	private final CrossConnectBandwidthDao ccBandwidthDao = DAOFactory
			.getInstance().getCrossConnectBandwidthDao();

	/**
	 * The Class TPComparator.
	 */
	public static class TPComparator implements Comparator<TerminationPoint> {

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		@Override
		public int compare(TerminationPoint first, TerminationPoint second) {

			int firstSlot = Integer.valueOf(first.getPort());
			int secondSlot = Integer.valueOf(second.getPort());

			if (firstSlot < secondSlot) {
				return -1;

			} else if (firstSlot == secondSlot) {
				return 0;
			} else {
				return 1;
			}

		}

	}

	/**
	 * Gets the port utilization.
	 * 
	 * @param cardname
	 *            the cardname
	 * @param port
	 *            the port
	 * @param usedbandwidth
	 *            the usedbandwidth
	 * @return the port utilization
	 */
	@Override
	public String getPortUtilization(String cardname, String port,
			long usedbandwidth) {

		if(0 >= usedbandwidth) {
			return "0";
		}
		String utilization = "";
		String portbandwidth = getPortTotalBandwidth(cardname, port);
		if (!StringUtil.isEmptyString(portbandwidth)) {
			double totbandwidth = Double.valueOf(portbandwidth);
			double utiliaed = Math.min(1.0, usedbandwidth / totbandwidth / 2);
			// CommonLogger.info(this, "port utilized: " + utiliaed);
			utilization = MessageFormat.format("{0,number,#.##}",
					utiliaed * 100);

		}

		return utilization;

	}

	/**
	 * Gets the card utilization.
	 * 
	 * @param usedPort
	 *            the used port
	 * @param totalPort
	 *            the total port
	 * @return the card utilization
	 */
	private String getCardUtilization(int usedPort, int totalPort) {

		String utilization = "0";
		if (totalPort != 0) {

			double utiliaed = (double) usedPort / totalPort;
			CommonLogger.info(this, "card utilized: " + utiliaed);
			utilization = MessageFormat.format("{0,number,#.##}",
					utiliaed * 100);

		}

		return utilization;

	}

	/**
	 * Gets the port total bandwidth.
	 * 
	 * @param cardname
	 *            the cardname
	 * @param port
	 *            the port
	 * @return the port total bandwidth
	 */
	private String getPortTotalBandwidth(String cardname, String port) {
		String combinationname = cardname + "-" + port;
		String portbandwidth = AppConstants.PORTCAPACITYMAP.get(cardname);

		if (AppConstants.PORTCAPACITYMAP.containsKey(combinationname)) {
			portbandwidth = AppConstants.PORTCAPACITYMAP.get(combinationname);
		}
		return portbandwidth;
	}

	/**
	 * Gets the pT psby n eand slot.
	 * 
	 * @param neId
	 *            the ne id
	 * @param tlMap
	 *            the tl map
	 * @param ccMap
	 *            the cc map
	 * @param fdfrMap
	 *            the fdfr map
	 * @param eqVo
	 *            the eq vo
	 * @return the pT psby n eand slot
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void getPTPsbyNEandSlot(String neId,
			HashMultimap<String, TopologicalLinkVo> tlMap,
			HashMultimap<String, CrossConnectVo> ccMap,
			HashMultimap<String, FDFrVo> fdfrMap, EquipmentVo eqVo)
			throws DAOException {

		String slotId = eqVo.getSlot();
		List<TerminationPoint> tpList = DAOFactory.getInstance().getTPDao()
				.findTPbyNEAndSlot(neId, slotId);

		Collections.sort(tpList, new TPComparator());

		List<TerminationPointVo> tpVos = new ArrayList<TerminationPointVo>();

		int cardUtilization = 0;

		for (TerminationPoint tp : tpList) {

			int usedbandwidth = 0;

			String port = tp.getPort();
			TerminationPointVo tpVo = new TerminationPointVo(eqVo.getName(),
					slotId, port);

			String keyString = TPNameMapper.generateKey(slotId, port);
			Set<TopologicalLinkVo> tLinks = tlMap.get(keyString);

			Set<CrossConnectVo> ccList = ccMap.get(keyString);

			Set<FDFrVo> fdfrList = fdfrMap.get(keyString);

			if (tLinks != null && tLinks.size() > 0) {
				cardUtilization += 1;
			}
			tpVo.setTopologicalLinks(Lists.newArrayList(tLinks));
			tpVo.setFdfrs(Lists.newArrayList(fdfrList));
			tpVo.setCrossConnects(Lists.newArrayList(ccList));
			usedbandwidth = getTotalBandwidthOfPort(ccList);

			tpVo.setUtilization(getPortUtilization(eqVo.getType(), port,
					usedbandwidth));
			tpVo.setUsedbandwidth(String.valueOf(usedbandwidth / 2));
			tpVo.setTotalbandwidth(getPortTotalBandwidth(eqVo.getName(), port));
			tpVo.setUtilization(getPortUtilization(eqVo.getName(), port,
					usedbandwidth));
			tpVos.add(tpVo);
		}

		eqVo.setUtilization(getCardUtilization(cardUtilization, tpList.size()));
		eqVo.setTotalports(String.valueOf(tpList.size()));
		eqVo.setUsedport(String.valueOf(cardUtilization));
		eqVo.setTerminationPoints(tpVos);

	}

	private int getTotalBandwidthOfPort(Set<CrossConnectVo> ccList)
			throws DAOException {

		int totalBandwidth = 0;
		for (CrossConnectVo cc : ccList) {

			CrossConnectBandwidth ccBandwidth = ccBandwidthDao
					.getCrossConnectBandwidthbyName(cc.getNativeEmsName());
			if (ccBandwidth.getMaxbandwidth() > 0)
				totalBandwidth += ccBandwidth.getMaxbandwidth();
		}

		return totalBandwidth;
	}

	@Override
	public int getTotalBandwidthOfPort(List<CrossConnect> ccList)
			throws DAOException {

		int totalBandwidth = 0;
		for (CrossConnect cc : ccList) {

			CrossConnectBandwidth ccBandwidth = ccBandwidthDao
					.getCrossConnectBandwidthbyName(cc.getEmsNativeName());

			if (ccBandwidth != null) {
				if (ccBandwidth.getMaxbandwidth() > 0) {
					totalBandwidth += ccBandwidth.getMaxbandwidth();
				} else if (ccBandwidth.getMaxbandwidth() == 0) {

					String bandwidthByName = CrossConnectControllerImpl
							.getTunnelbandwidthbyName(ccBandwidth
									.getEmsNativeName());
					totalBandwidth += Integer.valueOf(bandwidthByName);
				}
			}
		}

		return totalBandwidth;
	}

}
